﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Xml;

namespace DnnDash.DesktopDashboard
{
    public partial class frmMain : Form
    {
        Authentication _credentials;
        internal frmMain(Authentication credentials)
        {
            InitializeComponent();
            Application.ThreadException += Application_ThreadException;
            _credentials = credentials;
            
            //Call the PingHost routine to establish that the credentials are correct
            HttpStatusCode statusCode; string errorMsg = null;
            string ver = PingServerForAuthentication(credentials, out statusCode, out errorMsg);
            switch (statusCode)
            {
                case HttpStatusCode.OK:
                    lblDashVersion.Text = ver;
                    string activeTabName = GetActiveTabName(credentials);
                    GetAndShowSettings(activeTabName);
                    break;
                default:
                    lblDashVersion.Text = "ERROR";
                    break;
            }
            
        }

        void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
        {
            Exception ex = e.Exception;
            MessageBox.Show("An Error Occurred.  : " + ex.Message + " \n\n " + ex.StackTrace, "Exception in Application", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }



        private void btnRefresh_Click(object sender, EventArgs e)
        {
            GetAndShowSettings(null);
        }
        private void btnSetActiveTab_Click(object sender, EventArgs e)
        {
            SetActiveTabAsFavorite(tabDashboard.SelectedTab);
        }
        #region UI Control
        private void GetAndShowSettings(string activeTabName)
        {
            XmlDocument settings = GetSettingsFromSite();
            if (settings != null)
            {
                tabDashboard.TabPages.Clear();
                int tabIdx = -1; int selTab = 0;
                XmlNodeList dashControlNodes = settings.SelectNodes("dashboard/dashControl");
                foreach (XmlNode dashControl in dashControlNodes)
                {
                    string name = GetSafeAttribute(dashControl, "name", "Unknown Dashboard Type");
                    //dash tab
                    TabPage dashTabPage = new TabPage(name);
                    tabDashboard.TabPages.Add(dashTabPage);
                    tabIdx++;
                    if (activeTabName != null && string.Compare(activeTabName, name, true) == 0)
                        selTab = tabIdx;
                    XmlNode topChild = dashControl.FirstChild;

                    if (topChild != null)
                    {
                        string firstChildName = "";
                        XmlNodeList settingNodes = null;
                        XmlNodeList multipleNodes = null;
                        bool multiples = false;
                        int height = 0;
                        if (topChild.ChildNodes.Count > 0)
                        {
                            firstChildName = topChild.FirstChild.Name;
                            if (topChild.SelectNodes(firstChildName).Count > 1
                                || topChild.FirstChild.ChildNodes.Count > 1)
                            {
                                multipleNodes = topChild.SelectNodes(firstChildName);
                                multiples = true;
                                height = 25 * multipleNodes.Count + 125;
                            }
                            else
                            {
                                settingNodes = topChild.ChildNodes;
                                height = 25 * topChild.ChildNodes.Count + 125; 
                            }
                        }
                        Control listViewContainer = dashTabPage;
                        Panel containerPanel = new Panel();
                        containerPanel.Left = 0;
                        containerPanel.Top = 0;
                        containerPanel.AutoScroll = true;
                        containerPanel.Width = dashTabPage.Width;
                        containerPanel.Height = dashTabPage.Height;
                        dashTabPage.Controls.Add(containerPanel);
                        
                        Accordion accordion;
                        string settingSetName;
                        //add an accordion control to the page
                        accordion = new Accordion();
                        accordion.AutoSize = false;
                        accordion.AutoScroll = true;
                        accordion.Size = new Size(containerPanel.Width - 25, height);
                        //accordion.Dock = DockStyle.Left;
                        containerPanel.Controls.Add(accordion);

                        if (!multiples)
                        {
                            //single node list - ie host/server where there is only one instance of settings
                            settingSetName = topChild.Name;
                            Expander singleExpander = new Expander();
                            singleExpander.BorderStyle = BorderStyle.FixedSingle;
                            ExpanderHelper.CreateLabelHeader(singleExpander, settingSetName, SystemColors.ActiveBorder);
                            accordion.Add(singleExpander);
                            listViewContainer = singleExpander;

                            //now add a list view control to the accordian expander
                            ListView lvwDash = CreateListView();
                            listViewContainer.Controls.Add(lvwDash);

                            FillListView(settingNodes, lvwDash);
                        }
                        else
                        {
                            foreach (XmlNode topLevelNode in multipleNodes)
                            {
                                settingSetName = firstChildName + " - " +  topLevelNode.FirstChild.InnerText;
                                Expander childNodeExpander = new Expander();
                                childNodeExpander.BorderStyle = BorderStyle.FixedSingle;
                                //childNodeExpander.MinimumSize = new System.Drawing.Size(400, 50);
                                ExpanderHelper.CreateLabelHeader(childNodeExpander, settingSetName, SystemColors.ActiveBorder);
                                accordion.Add(childNodeExpander);
                                listViewContainer = childNodeExpander;

                                //now add a list view control to the accordian expander
                                ListView lvwDash = CreateListView();
                                listViewContainer.Controls.Add(lvwDash);
                                FillListView(topLevelNode.ChildNodes, lvwDash);
                            }
                        }
                        
                    }
                }
                //select the one that was supplied as the active tab
                if (tabIdx >= 0 && selTab >= 0)
                    tabDashboard.SelectedIndex = selTab;
            }
        }
        private ListView CreateListView()
        {
            ListView lvwDash = new ListView();
            ColumnHeader col1 = lvwDash.Columns.Add("name", "Setting");
            ColumnHeader col2 = lvwDash.Columns.Add("value", "Value");
            col1.Width = 100;
            col2.Width = 370;
            lvwDash.View = View.Details;
            lvwDash.Height = 400;
            lvwDash.Width = 470;
            return lvwDash;

        }
        private void FillListView(XmlNodeList settingNodes, ListView lvwDash)
        {
            foreach (XmlNode childNode in settingNodes)
            {
                List<string> stuff = new List<string>();
                stuff.Add(childNode.Name);
                stuff.Add(childNode.InnerText);
                lvwDash.Items.Add(new ListViewItem(stuff.ToArray()));
            }
        }
        private void CreateContentLabel(Expander expander, string text, int height)
        {
            Label labelContent = new Label();
            labelContent.Text = text;
            labelContent.Size = new System.Drawing.Size(expander.Width, height);
            expander.Content = labelContent;
        }
        private string GetSafeAttribute(XmlNode node, string name, string defaultValue)
        {
            string result = defaultValue;
            XmlAttribute att = node.Attributes[name];
            if (att != null)
            {
                result = att.Value.ToString();
            }
            return result;
        }
        #endregion
        #region service calls
        /// <summary>
        /// Call the Authenticated Ping method of the site to establish credentials
        /// </summary>
        /// <param name="credentials"></param>
        /// <param name="statusCode"></param>
        /// <param name="errorMsg"></param>
        /// <returns></returns>
        private string PingServerForAuthentication(Authentication credentials, out HttpStatusCode statusCode, out string errorMsg)
        {
            string verUrl = DnnRequest.GetUrl(credentials.HttpAlias, "DnnDash_SimpleDashboard", "Dash", "PingHost", false);
            CookieContainer cookies = _credentials.Cookies;
            string ver = DnnRequest.GetRequest(verUrl, _credentials.Username, _credentials.Password, out statusCode, out errorMsg, ref cookies);
            return ver;
        }
        /// <summary>
        /// Call service to get the list of settings
        /// </summary>
        /// <returns></returns>
        private XmlDocument GetSettingsFromSite()
        {
            XmlDocument result = null;
            string settingsUrl = DnnRequest.GetUrl(_credentials.HttpAlias, "DnnDash_SimpleDashboard", "Dash", "Controls", false);
            CookieContainer cookies = _credentials.Cookies;
            HttpStatusCode statusCode;
            string errorMsg;
            bool retry = true;
            while (retry)
            {
                retry = false;
                string settingsXml = DnnRequest.GetXmlRequest(settingsUrl, _credentials.Username, _credentials.Password, out statusCode, out errorMsg, ref cookies);
                switch (statusCode)
                {
                    case HttpStatusCode.OK:
                        result = new XmlDocument();
                        //string quote = '"'.ToString();
                        //if (settingsXml.StartsWith(quote) && settingsXml.EndsWith(quote))
                        //    settingsXml = settingsXml.Substring(1, settingsXml.Length - 1);
                        result.LoadXml(settingsXml);
                        break;

                    default:
                        //error = everything else
                        if (MessageBox.Show(string.Format("Error in API Call \n\n Status Code : {0} \n\n Error : {1}", statusCode, errorMsg)
                            , "API Call Unexpected Result", MessageBoxButtons.RetryCancel) == System.Windows.Forms.DialogResult.Retry)
                        {
                            //if retry button, will call the API again
                            retry = true;
                        }
                        break;
                }
            }
            return result;
        }
        /// <summary>
        /// Call service to retrieve Favorite tab name for the settings
        /// </summary>
        /// <param name="credentials"></param>
        /// <returns></returns>
        private string GetActiveTabName(Authentication credentials)
        {
            string url = DnnRequest.GetUrl(_credentials.HttpAlias, "DnnDash_SimpleDashboard", "Dash", "FavoriteDashControl", false);
            HttpStatusCode statusCode; string errorMsg;
            CookieContainer cookies = _credentials.Cookies;
            SimpleResult result = DnnRequest.GetJsonRequest(url, credentials.Username, credentials.Password, out statusCode, out errorMsg, ref cookies);
            //
            if (result.Result == "success")
                return result.data.Trim();
            else
                return "";
        }
        /// <summary>
        /// sets the active tab and stores by calling the server
        /// </summary>
        /// <param name="tabPage"></param>
        private void SetActiveTabAsFavorite(TabPage tabPage)
        {
            string name = tabPage.Text;
            string url = DnnRequest.GetUrl(_credentials.HttpAlias, "DnnDash_SimpleDashboard", "Dash", "FavoriteDashControl", false);
            HttpStatusCode statusCode; string errorMsg;
            string request = @"{ ""data"" : "" name "" } ".Replace("name", name);
            CookieContainer cookies = _credentials.Cookies;
            string result = DnnRequest.PostJsonRequest(url, _credentials.Username, _credentials.Password, request, out statusCode, out errorMsg, ref cookies);
            switch (statusCode)
            {
                case HttpStatusCode.OK:

                    break;
                default:
                    MessageBox.Show(string.Format("Error in API Call \n\n Status Code : {0} \n\n Error : {1}", statusCode, errorMsg), "API Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;
            }
        }
        #endregion
    }
}
